package com.aisino.file.compression;

import com.aisino.file.compression.exception.MyZipException;

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * 文件压缩合并工具类
 *
 * @author jiangf
 */
public class ZipUtils {

    /**
     * 合并 zip 文件, 若 fileList 中文件出现重复, fileList 中顺序靠后文件的相同文件会覆盖靠前文件的内容.
     *
     * @param zipFile     合并后写入的文件
     * @param fileList 合并文件列表集合
     */
    private static void mergeZipFile(File zipFile, List<File> fileList) {
        try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile))) {
            byte[] buffer = new byte[512];
            int len;

            for (int i = fileList.size() - 1; i >= 0; i--) {
                File source = fileList.get(i);
                ZipFile original = new ZipFile(source);

                Enumeration<? extends ZipEntry> entries = original.entries();

                while (entries.hasMoreElements()) {
                    final ZipEntry srcEntry = entries.nextElement();
                    ZipEntry entry = new ZipEntry(srcEntry.getName());

                    try {
                        out.putNextEntry(entry);

                        InputStream in = original.getInputStream(entry);
                        while ((len = in.read(buffer)) >= 0)
                            out.write(buffer, 0, len);

                        out.closeEntry();
                    } catch (ZipException e) {
                        throw new MyZipException(e);
                    }
                }
            }
        } catch (FileNotFoundException e) {
            throw new MyZipException(e);
        } catch (IOException e) {
            throw new MyZipException(e);
        }
    }

    /**
     * 合并 zip 文件, 若 files 中文件出现重复, files 中顺序靠后文件的相同文件会覆盖靠前文件的内容.
     *
     * @param dest  合并后写入的文件
     * @param files 合并文件列表
     */
    private static void mergeZipFile(File dest, File... files) {
        List<File> fileList = Arrays.asList(files);
        mergeZipFile(dest, fileList);
    }

    /**
     * 合并 zip 文件, 若 paths 中文件出现重复, paths 中顺序靠后文件的相同文件会覆盖靠前文件的内容.
     *
     * @param dest  合并后写入的文件
     * @param paths 合并文件列表
     */
    private static void mergeZipFile(File dest, String... paths) {
        List<File> collect = Arrays.stream(paths).map(p -> new File(p)).collect(Collectors.toList());
        mergeZipFile(dest, collect);
    }

    /**
     * 合并 zip 文件, 若 paths 中文件出现重复, paths 中顺序靠后文件的相同文件会覆盖靠前文件的内容.
     *
     * @param zipPath  合并后写入的文件
     * @param paths 合并文件列表
     */
    private static void mergeZipFile(String zipPath, String... paths) {
        List<File> collect = Arrays.stream(paths).map(p -> new File(p)).collect(Collectors.toList());
        mergeZipFile(new File(zipPath), collect);
    }

    /**
     * 合并 zip 文件, 若 src 中文件出现重复, src 中顺序靠后文件的相同文件会覆盖靠前文件的内容.
     *
     * @param zipPath     合并后写入的文件
     * @param pathList 合并文件列表
     */
    private static void mergeZipFile(String zipPath, List<String> pathList) {
        List<File> collect = pathList.stream().map(p -> new File(p)).collect(Collectors.toList());
        mergeZipFile(new File(zipPath), collect);
    }


//    public static void main(String[] args) {
//        File zipFile = new File("F:\\mergeZipFileTest.zip");
//        File file1 = new File("F:\\压缩包\\nginx-1.20.1.zip");
//        File file2 = new File("F:\\压缩包\\site-1.10.11.zip");
//        File file3 = new File("F:\\压缩包\\devtools-hide-inspect-button-outside-chrome-devtools-context.zip");
//        File file4 = new File("F:\\压缩包\\jdk-11.0.12_windows-x64_bin.zip");
//        File file5 = new File("F:\\压缩包\\mysql-8.0.26-winx64.zip");
//        File file6 = new File("F:\\压缩包\\Redis-x64-3.2.100.zip");
//        File[] files = {file1, file2, file3, file4, file5, file6};
//        String[] strs = {"F:\\压缩包\\apache-maven-3.8.2-bin.tar.gz", "F:\\压缩包\\apache-tomcat-9.0.54.tar.gz", "F:\\压缩包\\devtools-hide-inspect-button-outside-chrome-devtools-context.zip"};
//        zipFiles(zipPath, files);
//        zipFiles(zipPath, files);
//        mergeZipFile(zipFile, new File[]{new File("F:\\压缩包\\Genshin-Gacha-Export.zip")});
//    }

}
